package top.milkbox.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import top.milkbox.domain.User;
import top.milkbox.info.R;
import top.milkbox.info.requestBody.CodeAndEmail;
import top.milkbox.service.EmailVerificationCodeService;
import top.milkbox.service.UserService;


import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


@Slf4j
@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private EmailVerificationCodeService emailVCS;

    /**
     * 使用邮箱登录或注册
     *
     * @param session      主要用来验证邮箱验证码的
     * @param response     主要用来操作cookie
     * @param codeAndEmail 邮箱验证码和邮箱地址
     * @return R
     */
    @PostMapping("/emailLogin")
    private R emailLoginOrRegister(
            HttpSession session,
            HttpServletResponse response,
            @RequestBody CodeAndEmail codeAndEmail
    ) {
        R r = new R();
        Boolean isPass = emailVCS.checkEmail(session, codeAndEmail.getEmail(), codeAndEmail.getCode());
        r.setFlag(isPass);
        if (!isPass) {
            r.setMessage("邮箱验证错误");
            return r;
        }
        // 校验通过

        // 查询数据库中是否有此邮箱，如果有则将用户信息存入redis完成登录
        User user = userService.getFromEmail(codeAndEmail.getEmail());
        if (user != null) { // 用户已经注册
            String token = userService.generateToken(user.getUserId());
            log.debug("生成token：" + token);
            int status = userService.setUserToRedis(token, user);// 存入redis
            userService.setTokenToCookieToResponse(token, response); // 存入cookie
            log.debug("用户已存在，直接登录");

            if (status == 0) {
                r.setMessage("只允许同时2个设备登录，已将最早活跃的设备下线");
            } else {
                r.setMessage("登录成功");
            }

        } else {
            // 如果没有此邮箱数据，则进行注册（插入数据库数据）
            // 然后再执行登录（将用户信息存入redis）

            log.debug("用户不存在，准备注册...");
            // 向数据库中插入用户信息，并获取插入的信息
            User registeredUser = userService.register(codeAndEmail.getEmail());
            if (registeredUser != null) { // 插入成功
                // 登录
                String token = userService.generateToken(registeredUser.getUserId());
                log.debug("生成token：" + token);
                userService.setUserToRedis(token, registeredUser); // 存入redis
                userService.setTokenToCookieToResponse(token, response); // 存入cookie

                r.setMessage("您尚未注册，自动完成注册并登录成功");
            } else { // 插入失败，此时多半是由于数据库报错
                r.setFlag(false);
                r.setMessage("注册用户失败");
                return r;
            }
        }

        return r;
    }


    /**
     * 获取Redis中的用户信息
     * 如果此请求被设置拦截器，则当用户未登录的时候根本不会经过这里
     *
     * @param token 设备的token
     * @return R
     */
    @GetMapping("/getUser.login")
    private R getUserFromRedisByToken(@CookieValue("token") String token) {
        R r = new R();
        User user = userService.getUserFromRedis(token);
        if (user != null) {
            r.setFlag(true);
            r.setMessage("信息获取成功");
        } else {
            r.setFlag(false);
            r.setMessage("未查询到用户的session信息，请先登录");
        }
        r.setData(user);
        return r;
    }


    /**
     * 当前设备退出登录
     * 拦截器校验
     *
     * @param token 设备的token
     * @return R
     */
    @GetMapping("/logoutCurrent.login")
    private R userLogoutCurrent(@CookieValue("token") String token, HttpServletResponse response) {
        userService.removeUserFromRedisForCurrentDevice(token);
        userService.removeTokenCookieFromResponse(response);
        return new R(true, null, "当前设备登出成功");
    }

    /**
     * 所有设备退出登录
     * 拦截器校验
     *
     * @param token 设备的token
     * @return R
     */
    @GetMapping("/logoutAll.login")
    private R userLogoutAll(@CookieValue("token") String token, HttpServletResponse response) {
        userService.removeUserFromRedisForAllDevice(token);
        userService.removeTokenCookieFromResponse(response);
        return new R(true, null, "所有全部登出成功");
    }

    /**
     * 重置用户头像
     * 拦截器校验
     *
     * @param token 设备的token
     * @return R
     */
    @GetMapping("/resetUserAvatar.login")
    private R resetUserAvatar(@CookieValue("token") String token) {
        Boolean isReset = userService.resetUserAvatar(token);
        R r = new R();
        r.setFlag(isReset);
        if (isReset) {
            r.setMessage("头像重置成功");
        } else {
            r.setMessage("头像重置失败");
        }

        return r;
    }

    /**
     * 修改用户头像
     * 拦截器校验
     *
     * @param token  设备的token
     * @param avatar 头像文件
     * @return R
     */
    @PostMapping("/uploadAvatar.login")
    private R uploadAvatar(
            @CookieValue("token") String token,
            MultipartFile avatar) {
        R r = new R();
        Boolean isSave = userService.saveUserAvatar(token, avatar);
        r.setFlag(isSave);
        if (isSave) {
            r.setMessage("头像上传成功");
        } else {
            r.setMessage("头像上传失败");
        }

        return r;
    }

    /**
     * 修改用户昵称
     * 拦截器校验
     *
     * @param token 设备的token
     * @param user  用户对象，只用到用户昵称
     * @return R
     */
    @PutMapping("/changeNickname.login")
    private R changeUserNickname(@CookieValue("token") String token, @RequestBody User user) {
        R r = new R();
        Boolean isChange = userService.changeUserNickname(token, user.getUserNickname());
        r.setFlag(isChange);
        if (isChange) {
            r.setMessage("昵称修改成功");
        } else {
            r.setMessage("昵称修改失败");
        }

        return r;
    }

}
